#! /usr/bin/env bash

MONGO=mongo
TMPFOLDER=/tmp
SCRIPT="
var count = 0;
var resultstr = 0;
function isEmptyObject(obj) {
    for (var name in obj) {
        return false;
    }

    return true;
}

function getQueryOrRemove(obj) {
    if(!isEmptyObject(obj.query)) {
        return obj.op + '(' + tojson(obj.query) + ')';
    } else {
        return obj.op + '()';
    }
}

function safe_assign(from, to) {
    if(!isEmptyObject(from)) {
        to = from;
    }
}

function getUpdate(obj) {
    command = obj.op + '(';
    if(!isEmptyObject(obj.query))  {
        command += tojson(obj.query);
    }
    if(!isEmptyObject(obj.updateobj)) {
        command += ', ' + tojson(obj.updateobj);
    }
    command += ')';

    return command;
}

function getCommand(obj) {
    if(isEmptyObject(obj.command)) {
        return obj.op + '(' + tojson(obj.command) + ')';
    } else {
        return obj.op + '()';
    }
}

function get_command(obj) {
    var str = new Array();
    str[0] = obj.ns
    if(obj.op == 'query' || obj.op == 'remove') {
        str[1] = getQueryOrRemove(obj);
    } else if (obj.op == 'update') {
        str[1] = getUpdate(obj);
    } else if (obj.op == 'insert') {
        str[1] = obj.op + '()';
    } else if (obj.op == 'command') {
        str[1] = getCommand(obj);
    }
    if(obj.ntoreturn >= 1) {
        str[2] = 'limit(' + obj.ntoreturn + ')';
    }
    return str.join('.');
}

function getOutput(dbName){
    var db = conn.getDB(dbName);
    var level = db.getProfilingLevel();

    if(level <= 0) {
        db.setProfilingLevel(1, %s);
    }

    var cursor = db.system.profile.find({%s}).sort({ts:-1}).limit(200);

    while(cursor.hasNext()) {
        var doc = tojson(cursor.next());
        var obj = eval('(' + doc + ')');
        output = new Array();
        output[0] = obj.ts.valueOf();
        output[1] = get_command(obj).replace(/\|/g,'<<VERTICAL>>');
        output[2] = '-';
        output[3] = '-';
        output[4] = '-';
        output[5] = '-';
        output[6] = '%s';

        if(!isEmptyObject(obj.nscanned)) {
            output[2] = obj.nscanned;
        }
        if(!isEmptyObject(obj.nreturned)) {
            output[3] = obj.nreturned;
        }
        if(!isEmptyObject(obj.millis)) {
            output[4] = obj.millis;
        }
        if(!isEmptyObject(obj.client)) {
            output[5] = obj.client;
        }
        count ++;
        resultstr+=(output.join('<<:>>') + '<<###>>');

    }
}

var conn = new Mongo('%s');
var list = db.adminCommand('listDatabases');
var showList = new Array();
for (cc in list.databases){
        var name = list.databases[cc].name;
        if(name!='local' && name!='test' && name!='admin'){
                showList.push(name);
        }
}

for(var i=0;i<showList.length;i++){
        getOutput(showList[i]);
}

if(count>0){
    print(count+'<<COUNT>>|MongoDB_Slow_Query<<###>>'+resultstr);
}else{
    print('');
}

"


function monitor {
	MONGO_LAST_TIME="mongo_info_${PORT}"
	if [[ -f ./$MONGO_LAST_TIME ]] ; then
		LAST_TIME=$(cat ./$MONGO_LAST_TIME)
		if [[ -n "$LAST_TIME" ]] ; then
			CONDITION="ts:{\$gt:new Date($LAST_TIME)}"
		fi
	fi
    printf "$SCRIPT" "$6" "$CONDITION" "$3" "$2:$3"> "$TMPFOLDER/mongo.js"
    OUTPUT=$("$1/$MONGO" "$2":"$3" "$TMPFOLDER/mongo.js" --quiet)
    if [[ -n "$OUTPUT" ]] ; then
        RECORD_TIME="0$(date +%s)000"
        echo "$RECORD_TIME" > ./$MONGO_LAST_TIME
    fi
}

function usage {
	printf "\nUsage check_mongo_slow_query:\n"
    printf "\t<-f mongo可执行程序的路径>\n"
    printf "\t<-w 设置告警状态的慢查询语句阈值>\n"
    printf "\t<-c 设置紧急状态的慢查询语句阈值>\n"
    printf "\t[-u 连接数据库的用户名]\n"
    printf "\t[-p 连接数据库的密码]\n"
    printf "\t[-P 连接数据库的端口]\n"
    printf "\t[-H 设置MongoDB服务器所在的主机IP地址]\n"
    printf "\t[-t 设置记录慢查询语句的时间阈值]\n"
    printf "\t-h 打印帮助信息\n"
}

while getopts :u:p:P:f:w:c:t:H:h arg; do
    case $arg in
    u) NAME=$OPTARG;;
    p) PASSWD=$OPTARG;;
		H) HOST=$OPTARG;;
		P) PORT=$OPTARG;;
		f) BINPATH=$OPTARG;;
		t) THRESHOLD=$OPTARG;;
    w) WARNING=$OPTARG;;
    c) CRITICAL=$OPTARG;;
		h) usage
       exit 0;;
		?) printf "无效的参数!\n"
       usage
       exit 3;;
    esac
done

if [[ ! -x "$BINPATH/$MONGO" ]] ; then
	printf "$BINPATH/$MONGO不是有效的可执行程序.\n"
    usage
    exit 3
fi

#set the default port
if [[ -z "$PORT" ]] ; then
    PORT=27017
fi

#set the default IP address
if [[ -z "$HOST" ]] ; then
    HOST=127.0.0.1
    #TODO:需要修改为127.0.0.1
fi

if [[ -z "$WARNING" || -z "$CRITICAL" ]] ; then
    printf "必须提供用于设置监控项状态的阈值.\n"
    usage
    exit 3
fi

#set the default threshold
if [[ -z "$THRESHOLD" ]] ; then
    THRESHOLD=100
fi

monitor "$BINPATH" "$HOST" "$PORT" "$NAME" "$PASSWD" "$THRESHOLD"

if [[ ! -z $OUTPUT ]] ; then
    # count=$(printf "%s" "$OUTPUT" | awk -F '<<###>>' 'print NF')
    # OUTPUT=$(echo $OUTPUT)      #删除OUTPUT中的换行符
    # printf "${count}<<COUNT>>|MongoDB_Slow_Query<<###>>%s\n" "$OUTPUT"
    #OUTPUT=`echo $OUTPUT|awk '{for(i=1;i<=NF;++i){if(index($0,"error")>1){print "not_master_and_slaveok_is_false";break;}}}'`
    OUTPUT=`echo $OUTPUT|awk '{for(i=1;i<=NF;++i){if(index($0,"error")>1){print "0";break;}}}'`
    echo $OUTPUT
    exit 1
else
    exit 0
fi
